﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using CalcEng;

namespace CalcApp
{
    public partial class Form1 : Form
    {
        Thread m_playThread;
        StreamWriter m_resultSW;
        List<CalcResult> m_cRets;

        delegate void SetTextCallback(string text);
        delegate void EnableStartBtnCallback();

        public Form1()
        {
            InitializeComponent();
            txtFolderPath.Text = @"D:\Program Files\gtja\JunhongYouPlus(NaturalVitality)\T0002\export";
            txbTdxPath.Text = @"D:\Program Files\gtja\JunhongYouPlus(NaturalVitality)";
            if (!Directory.Exists(txbTdxPath.Text))
            {
                txbTdxPath.Text = @"";
                cbxNewBlk.Enabled = false;
            }
        }

        private void btnFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBr = new FolderBrowserDialog();
            folderBr.SelectedPath = @"D:\Program Files\gtja\JunhongYouPlus(NaturalVitality)\T0002\export";

            if (folderBr.ShowDialog() == DialogResult.OK)
            {
                txtFolderPath.Text = folderBr.SelectedPath;               
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            m_playThread = new Thread(new ThreadStart(this.Calc));
            m_playThread.Start();
            btnStart.Enabled = false;
        }

        private void SetLogText(string str)
        {
            if (this.listBoxLog.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetLogText);
                this.Invoke(d, new object[] { str });
            }
            else
            {
                if (this.listBoxLog.Items.Count > 3000)
                {
                    listBoxLog.Items.Clear();
                }
                this.listBoxLog.Items.Add(str);
            }
        }

        private void EnableStartBtn()
        {

            if (this.btnStart.InvokeRequired)
            {
                EnableStartBtnCallback d = new EnableStartBtnCallback(EnableStartBtn);
                this.Invoke(d);
            }
            else
            {
                btnStart.Enabled = true;
                MessageBox.Show(this, string.Format("Done"));
            }
        }

        public void Calc()
        {
            DateTime dt = DateTime.Now;
            string outputfilename = string.Format("{0}\\{1}{2:d2}{3:d2}{4:d2}{5:d2}output.xls", 
                                            txtFolderPath.Text, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
            m_resultSW = new StreamWriter(outputfilename);
            CalcEngine.FormatOutfileHead(m_resultSW);

            DirectoryInfo theFolder = new DirectoryInfo(txtFolderPath.Text);
            DirectoryInfo[] dirInfo = theFolder.GetDirectories();
          
            List<Task> tasks = new List<Task>();
            Action<object> action = TaskCalcFolder;
            m_cRets = new List<CalcResult>();

            foreach (DirectoryInfo subFolder in dirInfo)
            {
                Task task = new Task(action, (object)subFolder);
                task.Start();
                tasks.Add(task);
            }

            CalcFolder(theFolder, m_resultSW);

            Task.WaitAll(tasks.ToArray());
            m_resultSW.Close();
            m_resultSW = null;
            tasks.Clear();

           /* if (cbxNewBlk.Checked)
            { 
                string blkName =  string.Format("Cskb{0}{1:d2}{2:d2}{3:d2}{4:d2}", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
                BlockNew.WriteToBlocks(blkName, txbTdxPath.Text, m_cRets);
            }*/

            if (cbxHtml.Checked)
            {
                SetLogText("Updating HTMLs...");
                Dictionary<string, List<CalcResult>> dict = new Dictionary<string, List<CalcResult>>();
                foreach (CalcResult cre in m_cRets)
                {
                    List<CalcResult> cretList;
                    if (dict.ContainsKey(cre.code))
                    {
                        cretList = dict[cre.code];
                    }
                    else
                    {
                        cretList = new List<CalcResult>();
                        dict.Add(cre.code, cretList);
                    }
                    cretList.Add(cre);
                }

                action = TaskUpdateHtml;
                foreach (List<CalcResult> cretList in dict.Values)
                {
                    Task task = new Task(action, (object)cretList);
                    task.Start();
                    tasks.Add(task);                    
                }
                Task.WaitAll(tasks.ToArray());
            }
           
            EnableStartBtn();
        }

        private void CalcFolder(DirectoryInfo dirInfo, StreamWriter sw)
        {
            List<CalcResult> cRets = new List<CalcResult>();

            FileInfo[] fileInfo = dirInfo.GetFiles();
            if (fileInfo.Count() > 0)
            {
                List<Task> tasks = new List<Task>();
                Action<object> action = TaskCalcSingleFile;

                foreach (FileInfo nextFile in fileInfo)
                {
                    string strext = Path.GetExtension(nextFile.FullName);
                    string code = Path.GetFileNameWithoutExtension(nextFile.FullName);
                    if ((String.Compare(".xls", strext, true) == 0 || String.Compare(".txt", strext, true) == 0) && code.Length == 6)
                    {
                        int icode;
                        if (int.TryParse(code, out icode))
                        {
                            CalcPara cp = new CalcPara();
                            cp.code = code;
                            cp.filename = nextFile.FullName;
                            cp.outstream = sw;

                            Task task = new Task(action, (object)cp);
                            task.Start();
                            tasks.Add(task);
                        }
                    }
                }
                Task.WaitAll(tasks.ToArray());
            }
        }

        private void TaskCalcFolder(object obj)
        {
            DirectoryInfo dirInfo = obj as DirectoryInfo;
            FileInfo[] fileInfo = dirInfo.GetFiles();           
            foreach (FileInfo nextFile in fileInfo)
            {
                string strext = Path.GetExtension(nextFile.FullName);
                string code = Path.GetFileNameWithoutExtension(nextFile.FullName);
                if ((String.Compare(".xls", strext, true) == 0 || String.Compare(".txt", strext, true) == 0) && code.Length == 6)
                {
                    int icode;
                    if (int.TryParse(code, out icode))
                    {
                        CalcPara cp = new CalcPara();
                        cp.code = code;
                        cp.filename = nextFile.FullName;
                        cp.outstream = m_resultSW;
                        CalcResult cre = CalcEngine.Calc(cp);
                        if (cre != null)
                        {
                            Monitor.Enter(m_cRets);
                            m_cRets.Add(cre);
                            Monitor.Exit(m_cRets);
                        }
                        SetLogText("Calced " + nextFile.FullName);
                    }
                }
            }
        }

        private void txtFolderPath_TextChanged(object sender, EventArgs e)
        {
            int n = txtFolderPath.Text.IndexOf(@"\T0002\");
            if (n > 0)
            {
                txbTdxPath.Text = txtFolderPath.Text.Substring(0, n);
                cbxNewBlk.Enabled = true;
            }
            else
            {
                txbTdxPath.Text = "";
                cbxNewBlk.Checked = false;
                cbxNewBlk.Enabled = false;
            }
        }

 
        private void TaskUpdateHtml(object obj)
        {
            List<CalcResult> cretList = obj as List<CalcResult>;
            SetLogText("Updating Html for " + cretList.ElementAt(0).code);
            HtmlEngine.UpdateHtml(txbTdxPath.Text, cretList);
        }

        private void TaskCalcSingleFile(object obj)
        {
            CalcPara cp = obj as CalcPara;
            CalcResult cre = CalcEngine.Calc(cp);
            if (cre != null)
            {
                Monitor.Enter(m_cRets);
                m_cRets.Add(cre);
                Monitor.Exit(m_cRets);
            }
            SetLogText("Calced " + cp.filename);
        }
    }
}
